/**
 * Copyright 2021 jianggujin (www.jianggujin.com).
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.jianggujin.dbfly.mybatis.builder;

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import com.jianggujin.dbfly.mybatis.JConfiguration;
import com.jianggujin.dbfly.mybatis.builder.JDefaultMappedStatementBuilder.JParser;
import com.jianggujin.dbfly.util.JAssert;
import com.jianggujin.dbfly.util.JBeanUtils;
import com.jianggujin.dbfly.util.JExceptionUtils;
import com.jianggujin.dbfly.util.JObjectRef;
import com.jianggujin.dbfly.util.JStringUtils;

/**
 * Mapper方法解析
 * 
 * @author jianggujin
 *
 */
public class JMapperMethodParser implements JParser {

    @Override
    public boolean support(JConfiguration configuration, Class<?> mapperClass, Method method, JObjectRef<Object> ref) {
        return method.isAnnotationPresent(JMappedStatementProvider.class);
    }

    @Override
    public void parse(JConfiguration configuration, Class<?> mapperClass, Method method, Document document,
            Element mapperElement, Object ref) {
        JMappedStatementProvider mappedStatementProvider = method.getAnnotation(JMappedStatementProvider.class);
        String methodName = mappedStatementProvider.method();
        if (JDefaultMappedStatementBuilder.DYNAMIC_METHOD.equals(methodName) || methodName.length() == 0) {
            methodName = method.getName();
        }
        Method invokeMethod = JBeanUtils.findMethod(mappedStatementProvider.type(), methodName, JConfiguration.class,
                Class.class, Method.class, Document.class, Element.class);
        JAssert.notNull(invokeMethod, JStringUtils.format("JMappedStatementProvider注解方法[{}.{}({}, {}, {}, {}, {})]不存在",
                mappedStatementProvider.type().getName(), methodName, JConfiguration.class.getName(),
                Class.class.getName(), Method.class.getName(), Document.class.getName(), Element.class.getName()));
        // 静态方法
        if (Modifier.isStatic(invokeMethod.getModifiers())) {
            JBeanUtils.invokeMethod(null, invokeMethod, configuration, mapperClass, method, document, mapperElement);
        } else {
            try {
                JBeanUtils.invokeMethod(mappedStatementProvider.type().newInstance(), invokeMethod, configuration,
                        mapperClass, method, document, mapperElement);
            } catch (Exception e) {
                throw JExceptionUtils.handleException(e);
            }
        }
    }

}
